#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

#include <strhelper.h>

// from wiki
// Any 8-bit byte value may be encoded with 3 characters, an "=" followed by
// two hexadecimal digits (0–9 or A–F) representing the byte's numeric value.
// For example, a US-ASCII form feed  character (decimal value 12) can be
// represented by "=0C", and a US-ASCII equal sign (decimal value 61) must be
// represented by "=3D". All characters except printable ASCII characters or
// end of line characters must be encoded in this fashion.

// 除了可打印字符与行结束符，其它字符都要编码

// All printable ASCII characters (decimal values between 33 and 126) may be
// represented by themselves, except "=" (decimal 61).

// 33 - 126 之间，除了 "=" 号外，都可以直接表示

// ASCII tab and space characters, decimal values 9 and 32, may be represented
// by themselves, except if these characters appear at the end of a line. If
// one of these characters appears at the end of a line it must be encoded as
// "=09" (tab) or "=20" (space).

// 空格与制表符可以直接表示，除非它们出现在行末

// If the data being encoded contains meaningful line breaks, they must be
// encoded as an ASCII CR LF sequence, not as their original byte values,
// neither directly nor via "=" signs. Conversely if byte values 13 and 10 have
// meanings other than end of line, then they must be encoded as =0D and =0A
// respectively.

// neither nor 二者都不
// 如果要编码的东东是有意义的换行，直接转成 =0D 和 =0A

// Lines of quoted-printable encoded data must not be longer than 76 characters
//  To satisfy this requirement without altering the encoded text, soft line
// breaks may be added as desired. A soft line break consists of an "=" at the
// end of an encoded line, and does not appear as a line break in the decoded
// text. These soft line breaks also allow encoding text without line breaks
// (or containing very long lines) for an environment where line size is
// limited, such as SMTP. A text line exceeding 1000 bytes cannot be encoded in
// e-mail in 8bit (identical, or clear text) encoding because of SMTP
// restrictions.

// 因为 quoted-printable 不能太长，所以编码的时候会换行
// 这个时候的换行是没有意义的

// A slightly modified version of quoted-printable is used in message headers;
// see MIME#Encoded-Word.

int
quoted_printable_decode(const char *in,
                        int         inlen,
                        char       *out,
                        int        *err)
{
    int  i;
    char *p;

    if (inlen < 0)
        inlen = strlen(in);

    if (err)
        *err = 0;
    p = out;
    i = 0;

    while (i < inlen) {
        if (in[i] == '=') {
            if (i + 2 < inlen) {
                if (str_is_all_hex(&in[i + 1], 2)) {
                    str_hex_to_bytes_not_check(&in[i + 1], 2, p);
                    ++p;

                    i += 3;
                }
                else if ((in[i + 1] == '\r' && in[i + 2] == '\n'))
                    i += 3;
                else if (in[i + 1] == '\n' || in[i + 1] == '\r')
                    i += 2;
                else {
                    if (err)
                        *err = i;
                    break;
                }
            }
            else if (i + 1 < inlen && (in[i + 1] == '\n' || in[i + 1] == '\r'))
                i += 2;
            else {
                if (err)
                    *err = i;
                break;
            }
        }
        else
            *p++ = in[i++];
    }
    *p = 0;

    return (i < inlen) ? -1 : (int) (p - out);
}
